home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / menubar.c < prev    next >
C/C++ Source or Header  |  2009-02-26  |  45KB  |  1,669 lines

  1. /*
  2.  * Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  *    menubar.c
  12.  *        This module handles the menu bar.
  13.  */
  14.  
  15. #include "globals.h"
  16.  
  17. #if defined(X3270_MENUS) /*[*/
  18.  
  19. #include <X11/StringDefs.h>
  20. #include <X11/Xaw/Command.h>
  21. #include <X11/Xaw/MenuButton.h>
  22. #include <X11/Xaw/Dialog.h>
  23. #include "Husk.h"
  24. #include "CmplxMenu.h"
  25. #include "CmeBSB.h"
  26. #include "CmeLine.h"
  27.  
  28. #include "appres.h"
  29. #include "objects.h"
  30. #include "resources.h"
  31.  
  32. #include "actionsc.h"
  33. #include "aboutc.h"
  34. #include "ftc.h"
  35. #include "hostc.h"
  36. #include "keymapc.h"
  37. #include "keypadc.h"
  38. #include "kybdc.h"
  39. #include "macrosc.h"
  40. #include "menubarc.h"
  41. #include "popupsc.h"
  42. #include "printerc.h"
  43. #include "printc.h"
  44. #include "savec.h"
  45. #include "screenc.h"
  46. #include "telnetc.h"
  47. #include "togglesc.h"
  48. #include "utilc.h"
  49. #include "xioc.h"
  50.  
  51. #define MACROS_MENU    "macrosMenu"
  52.  
  53. extern Widget        keypad_shell;
  54. extern int        linemode;
  55. extern Boolean        keypad_popped;
  56.  
  57. static struct scheme {
  58.     char *label;
  59.     char *scheme;
  60.     struct scheme *next;
  61. } *schemes, *last_scheme;
  62. static int scheme_count;
  63. static Widget  *scheme_widgets;
  64.  
  65. static struct charset {
  66.     char *label;
  67.     char *charset;
  68.     struct charset *next;
  69. } *charsets, *last_charset;
  70. static int charset_count;
  71. static Widget  *charset_widgets;
  72.  
  73. static void scheme_init(void);
  74. static void charsets_init(void);
  75. static void options_menu_init(Boolean regen, Position x, Position y);
  76. static void keypad_button_init(Position x, Position y);
  77. static void connect_menu_init(Boolean regen, Position x, Position y);
  78. static void macros_menu_init(Boolean regen, Position x, Position y);
  79. static void file_menu_init(Boolean regen, Dimension x, Dimension y);
  80. static void Bye(Widget w, XtPointer client_data, XtPointer call_data);
  81. static void menubar_in3270(Boolean in3270);
  82. static void menubar_linemode(Boolean in_linemode);
  83. static void menubar_connect(Boolean ignored);
  84. #if defined(X3270_PRINTER) /*[*/
  85. static void menubar_printer(Boolean printer_on);
  86. #endif /*]*/
  87. static void menubar_remodel(Boolean ignored unused);
  88.  
  89. #include "dot.bm"
  90. #include "arrow.bm"
  91. #include "diamond.bm"
  92. #include "no_diamond.bm"
  93. #include "ky.bm"
  94. #include "null.bm"
  95.  
  96.  
  97. /*
  98.  * Menu Bar
  99.  */
  100.  
  101. static Widget    menu_parent;
  102. static Boolean  menubar_buttons;
  103. static Widget   disconnect_button;
  104. static Widget   exit_button;
  105. static Widget   exit_menu;
  106. static Widget   macros_button;
  107. static Widget    ft_button;
  108. #if defined(X3270_PRINTER) /*[*/
  109. static Widget    printer_button;
  110. static Widget    assoc_button;
  111. static Widget    lu_button;
  112. static Widget    printer_off_button;
  113. #endif /*]*/
  114. static Widget   connect_button;
  115. static Widget   keypad_button;
  116. static Widget   linemode_button;
  117. static Widget   charmode_button;
  118. static Widget   models_option;
  119. static Widget   model_2_button;
  120. static Widget   model_3_button;
  121. static Widget   model_4_button;
  122. static Widget   model_5_button;
  123. static Widget    oversize_button;
  124. static Widget    extended_button;
  125. static Widget    m3278_button;
  126. static Widget    m3279_button;
  127. static Widget   keypad_option_button;
  128. static Widget    script_abort_button;
  129. static Widget    scheme_button;
  130. static Widget   connect_menu;
  131.  
  132. static Pixmap   arrow;
  133. Pixmap    dot;
  134. Pixmap    diamond;
  135. Pixmap    no_diamond;
  136. Pixmap    null;
  137.  
  138. static int    n_bye;
  139.  
  140. static void    toggle_init(Widget, int, const char *, const char *);
  141.  
  142. #define TOP_MARGIN    3
  143. #define BOTTOM_MARGIN    3
  144. #define LEFT_MARGIN    3
  145. #define KEY_HEIGHT    18
  146. #define KEY_WIDTH    70
  147. #define BORDER        1
  148. #define SPACING        3
  149.  
  150. #define MO_OFFSET    1
  151. #define CN_OFFSET    2
  152.  
  153. #define MENU_BORDER    2
  154.  
  155. #define    MENU_MIN_WIDTH    (LEFT_MARGIN + 3*(KEY_WIDTH+2*BORDER+SPACING) + \
  156.              LEFT_MARGIN + (ky_width+8) + 2*BORDER + SPACING + \
  157.              2*MENU_BORDER)
  158.  
  159. /*
  160.  * Compute the potential height of the menu bar.
  161.  */
  162. Dimension
  163. menubar_qheight(Dimension container_width)
  164. {
  165.     if (!appres.menubar || container_width < (unsigned) MENU_MIN_WIDTH)
  166.         return 0;
  167.     else
  168.         return TOP_MARGIN + KEY_HEIGHT+2*BORDER + BOTTOM_MARGIN +
  169.             2*MENU_BORDER;
  170. }
  171.  
  172. /*
  173.  * Initialize the menu bar.
  174.  */
  175. void
  176. menubar_init(Widget container, Dimension overall_width, Dimension current_width)
  177. {
  178.     static Widget menu_bar;
  179.     static Boolean ever = False;
  180.     Boolean mb_old;
  181.     Dimension height;
  182.  
  183.     if (!ever) {
  184.  
  185.         scheme_init();
  186.         charsets_init();
  187.         XtRegisterGrabAction(HandleMenu_action, True,
  188.             (ButtonPressMask|ButtonReleaseMask),
  189.             GrabModeAsync, GrabModeAsync);
  190.  
  191.         /* Create bitmaps. */
  192.         dot = XCreateBitmapFromData(display, root_window,
  193.             (char *) dot_bits, dot_width, dot_height);
  194.         arrow = XCreateBitmapFromData(display, root_window,
  195.             (char *) arrow_bits, arrow_width, arrow_height);
  196.         diamond = XCreateBitmapFromData(display, root_window,
  197.             (char *) diamond_bits, diamond_width, diamond_height);
  198.         no_diamond = XCreateBitmapFromData(display, root_window,
  199.             (char *) no_diamond_bits, no_diamond_width,
  200.             no_diamond_height);
  201.         null = XCreateBitmapFromData(display, root_window,
  202.             (char *) null_bits, null_width, null_height);
  203.  
  204.         /* Register interest in state transtions. */
  205.         register_schange(ST_3270_MODE, menubar_in3270);
  206.         register_schange(ST_LINE_MODE, menubar_linemode);
  207.         register_schange(ST_HALF_CONNECT, menubar_connect);
  208.         register_schange(ST_CONNECT, menubar_connect);
  209. #if defined(X3270_PRINTER) /*[*/
  210.         register_schange(ST_PRINTER, menubar_printer);
  211. #endif /*]*/
  212.         register_schange(ST_REMODEL, menubar_remodel);
  213.  
  214.         ever = True;
  215.     }
  216.  
  217.     height = menubar_qheight(current_width);
  218.     mb_old = menubar_buttons;
  219.     menubar_buttons = (height != 0);
  220.     if (menubar_buttons) {
  221.         if (menu_bar == (Widget)NULL) {
  222.             /* Create the menu bar. */
  223.             menu_bar = XtVaCreateManagedWidget(
  224.                 "menuBarContainer", huskWidgetClass, container,
  225.                 XtNborderWidth, MENU_BORDER,
  226.                 XtNwidth, overall_width - 2*MENU_BORDER,
  227.                 XtNheight, height - 2*MENU_BORDER,
  228.                 NULL);
  229.         } else {
  230.             /* Resize and map the menu bar. */
  231.             XtVaSetValues(menu_bar,
  232.                 XtNborderWidth, MENU_BORDER,
  233.                 XtNwidth, overall_width - 2*MENU_BORDER,
  234.                 NULL);
  235.             XtMapWidget(menu_bar);
  236.         }
  237.         menu_parent = menu_bar;
  238.     } else if (menu_bar != (Widget)NULL) {
  239.         /* Hide the menu bar. */
  240.         XtUnmapWidget(menu_bar);
  241.         menu_parent = container;
  242.     } else
  243.         menu_parent = container;
  244.  
  245.     /* "File..." menu */
  246.  
  247.     file_menu_init(mb_old != menubar_buttons, LEFT_MARGIN, TOP_MARGIN);
  248.  
  249.     /* "Options..." menu */
  250.  
  251.     options_menu_init(mb_old != menubar_buttons,
  252.         LEFT_MARGIN + MO_OFFSET*(KEY_WIDTH+2*BORDER+SPACING),
  253.         TOP_MARGIN);
  254.  
  255.     /* "Connect..." menu */
  256.  
  257.     if (!appres.reconnect)
  258.         connect_menu_init(mb_old != menubar_buttons,
  259.             LEFT_MARGIN + CN_OFFSET*(KEY_WIDTH+2*BORDER+SPACING),
  260.             TOP_MARGIN);
  261.  
  262.     /* "Macros..." menu */
  263.  
  264.     macros_menu_init(mb_old != menubar_buttons,
  265.         LEFT_MARGIN + CN_OFFSET*(KEY_WIDTH+2*BORDER+SPACING),
  266.         TOP_MARGIN);
  267.  
  268.     /* Keypad button */
  269.  
  270.     keypad_button_init(
  271.         (Position) (current_width - LEFT_MARGIN - (ky_width+8) -
  272.                 2*BORDER - 2*MENU_BORDER),
  273.         TOP_MARGIN);
  274. }
  275.  
  276. /*
  277.  * External entry points
  278.  */
  279.  
  280. /*
  281.  * Called when connected to or disconnected from a host.
  282.  */
  283. static void
  284. menubar_connect(Boolean ignored unused)
  285. {
  286.     /* Set the disconnect button sensitivity. */
  287.     if (disconnect_button != (Widget)NULL)
  288.         XtVaSetValues(disconnect_button,
  289.             XtNsensitive, PCONNECTED,
  290.             NULL);
  291.  
  292.     /* Set up the exit button, either with a pullright or a callback. */
  293.     if (exit_button != (Widget)NULL) {
  294.         if (PCONNECTED) {
  295.             /* Remove the immediate callback. */
  296.             if (n_bye) {
  297.                 XtRemoveCallback(exit_button, XtNcallback,
  298.                     Bye, 0);
  299.                 n_bye--;
  300.             }
  301.  
  302.             /* Set pullright for extra confirmation. */
  303.             XtVaSetValues(exit_button,
  304.                 XtNrightBitmap, arrow,
  305.                 XtNmenuName, "exitMenu",
  306.                 NULL);
  307.         } else {
  308.             /* Install the immediate callback. */
  309.             if (!n_bye) {
  310.                 XtAddCallback(exit_button, XtNcallback,
  311.                     Bye, 0);
  312.                 n_bye++;
  313.             }
  314.  
  315.             /* Remove the pullright. */
  316.             XtVaSetValues(exit_button,
  317.                 XtNrightBitmap, NULL,
  318.                 XtNmenuName, NULL,
  319.                 NULL);
  320.         }
  321.     }
  322.  
  323.     /* Set up the connect menu. */
  324.     if (!appres.reconnect && connect_menu != (Widget)NULL) {
  325.         if (PCONNECTED && connect_button != (Widget)NULL)
  326.             XtUnmapWidget(connect_button);
  327.         else {
  328.             connect_menu_init(True,
  329.                 LEFT_MARGIN +
  330.                 CN_OFFSET*(KEY_WIDTH+2*BORDER+SPACING),
  331.                 TOP_MARGIN);
  332.             if (menubar_buttons)
  333.                 XtMapWidget(connect_button);
  334.         }
  335.     }
  336.  
  337.     /* Set up the macros menu. */
  338.     macros_menu_init(True,
  339.         LEFT_MARGIN + CN_OFFSET*(KEY_WIDTH+2*BORDER+SPACING),
  340.         TOP_MARGIN);
  341.  
  342.     /* Set up the various option buttons. */
  343.     if (ft_button != (Widget)NULL)
  344.         XtVaSetValues(ft_button, XtNsensitive, IN_3270, NULL);
  345. #if defined(X3270_PRINTER) /*[*/
  346.     if (printer_button != (Widget)NULL)
  347.         XtVaSetValues(printer_button, XtNsensitive, IN_3270,
  348.             NULL);
  349.     if (assoc_button != (Widget)NULL)
  350.         XtVaSetValues(assoc_button, XtNsensitive,
  351.             !printer_running() && IN_3270 && IN_TN3270E,
  352.             NULL);
  353.     if (lu_button != (Widget)NULL)
  354.         XtVaSetValues(lu_button, XtNsensitive,
  355.             !printer_running() && IN_3270,
  356.             NULL);
  357. #endif /*]*/
  358.     if (linemode_button != (Widget)NULL)
  359.         XtVaSetValues(linemode_button, XtNsensitive, IN_ANSI, NULL);
  360.     if (charmode_button != (Widget)NULL)
  361.         XtVaSetValues(charmode_button, XtNsensitive, IN_ANSI, NULL);
  362. #if defined(X3270_ANSI) /*[*/
  363.     if (appres.toggle[LINE_WRAP].w[0] != (Widget)NULL)
  364.         XtVaSetValues(appres.toggle[LINE_WRAP].w[0],
  365.             XtNsensitive, IN_ANSI,
  366.             NULL);
  367. #endif /*]*/
  368.     if (appres.toggle[RECTANGLE_SELECT].w[0] != (Widget)NULL)
  369.         XtVaSetValues(appres.toggle[RECTANGLE_SELECT].w[0],
  370.             XtNsensitive, IN_ANSI,
  371.             NULL);
  372.     if (models_option != (Widget)NULL)
  373.         XtVaSetValues(models_option, XtNsensitive, !PCONNECTED, NULL);
  374.     if (extended_button != (Widget)NULL)
  375.         XtVaSetValues(extended_button, XtNsensitive, !PCONNECTED,
  376.             NULL);
  377.     if (m3278_button != (Widget)NULL)
  378.         XtVaSetValues(m3278_button, XtNsensitive, !PCONNECTED,
  379.             NULL);
  380.     if (m3279_button != (Widget)NULL)
  381.         XtVaSetValues(m3279_button, XtNsensitive, !PCONNECTED,
  382.             NULL);
  383. }
  384.  
  385. #if defined(X3270_PRINTER) /*[*/
  386. /* Called when the printer starts or stops. */
  387. static void
  388. menubar_printer(Boolean printer_on)
  389. {
  390.     XtVaSetValues(assoc_button, XtNsensitive,
  391.         !printer_on && IN_3270 && IN_TN3270E,
  392.         NULL);
  393.     XtVaSetValues(lu_button, XtNsensitive,
  394.         !printer_on && IN_3270,
  395.         NULL);
  396.     XtVaSetValues(printer_off_button, XtNsensitive, printer_on, NULL);
  397. }
  398. #endif /*]*/
  399.  
  400. void
  401. menubar_keypad_changed(void)
  402. {
  403.     if (keypad_option_button != (Widget)NULL)
  404.         XtVaSetValues(keypad_option_button,
  405.             XtNleftBitmap,
  406.             appres.keypad_on || keypad_popped ? dot : None,
  407.             NULL);
  408. }
  409.  
  410. /* Called when we switch between ANSI and 3270 modes. */
  411. static void
  412. menubar_in3270(Boolean in3270)
  413. {
  414.     if (ft_button != (Widget)NULL)
  415.         XtVaSetValues(ft_button, XtNsensitive, IN_3270, NULL);
  416. #if defined(X3270_PRINTER) /*[*/
  417.     if (printer_button != (Widget)NULL)
  418.         XtVaSetValues(printer_button, XtNsensitive, IN_3270,
  419.             NULL);
  420.     if (assoc_button != (Widget)NULL)
  421.         XtVaSetValues(assoc_button, XtNsensitive,
  422.             !printer_running() && IN_3270 && IN_TN3270E,
  423.             NULL);
  424.     if (lu_button != (Widget)NULL)
  425.         XtVaSetValues(lu_button, XtNsensitive,
  426.             !printer_running() && IN_3270,
  427.             NULL);
  428. #endif /*]*/
  429.     if (linemode_button != (Widget)NULL)
  430.         XtVaSetValues(linemode_button,
  431.             XtNsensitive, !in3270,
  432.             XtNleftBitmap, in3270 ? no_diamond
  433.                     : (linemode ? diamond : no_diamond),
  434.             NULL);
  435.     if (charmode_button != (Widget)NULL)
  436.         XtVaSetValues(charmode_button,
  437.             XtNsensitive, !in3270,
  438.             XtNleftBitmap, in3270 ? no_diamond
  439.                     : (linemode ? no_diamond : diamond),
  440.             NULL);
  441. #if defined(X3270_ANSI) /*[*/
  442.     if (appres.toggle[LINE_WRAP].w[0] != (Widget)NULL)
  443.         XtVaSetValues(appres.toggle[LINE_WRAP].w[0],
  444.             XtNsensitive, !in3270,
  445.             NULL);
  446. #endif /*]*/
  447.     if (appres.toggle[RECTANGLE_SELECT].w[0] != (Widget)NULL)
  448.         XtVaSetValues(appres.toggle[RECTANGLE_SELECT].w[0],
  449.             XtNsensitive, !in3270,
  450.             NULL);
  451. }
  452.  
  453. /* Called when we switch between ANSI line and character. */
  454. static void
  455. menubar_linemode(Boolean in_linemode)
  456. {
  457.     if (linemode_button != (Widget)NULL)
  458.         XtVaSetValues(linemode_button,
  459.             XtNleftBitmap, in_linemode ? diamond : no_diamond,
  460.             NULL);
  461.     if (charmode_button != (Widget)NULL)
  462.         XtVaSetValues(charmode_button,
  463.             XtNleftBitmap, in_linemode ? no_diamond : diamond,
  464.             NULL);
  465. }
  466.  
  467. /* Called to change the sensitivity of the "Abort Script" button. */
  468. void
  469. menubar_as_set(Boolean sensitive)
  470. {
  471.     if (script_abort_button != (Widget)NULL)
  472.         XtVaSetValues(script_abort_button,
  473.             XtNsensitive, sensitive,
  474.             NULL);
  475. }
  476.  
  477.  
  478. /*
  479.  * "File..." menu
  480.  */
  481. static Widget save_shell = (Widget) NULL;
  482.  
  483. /* Called from "Exit x3270" button on "File..." menu */
  484. static void
  485. Bye(Widget w unused, XtPointer client_data unused, XtPointer call_data unused)
  486. {
  487.     x3270_exit(0);
  488. }
  489.  
  490. /* Called from the "Disconnect" button on the "File..." menu */
  491. static void
  492. disconnect(Widget w unused, XtPointer client_data unused,
  493.     XtPointer call_data unused)
  494. {
  495.     host_disconnect(False);
  496. }
  497.  
  498. /* Called from the "Abort Script" button on the "File..." menu */
  499. static void
  500. script_abort_callback(Widget w unused, XtPointer client_data unused,
  501.     XtPointer call_data unused)
  502. {
  503.     abort_script();
  504. }
  505.  
  506. /* "About x3270" popup */
  507. static void
  508. show_about(Widget w unused, XtPointer userdata unused,
  509.     XtPointer calldata unused)
  510. {
  511.     popup_about();
  512. }
  513.  
  514. /* Called from the "Save" button on the save options dialog */
  515. static void
  516. save_button_callback(Widget w unused, XtPointer client_data,
  517.     XtPointer call_data unused)
  518. {
  519.     char *s;
  520.  
  521.     s = XawDialogGetValueString((Widget)client_data);
  522.     if (!s || !*s)
  523.         return;
  524.     if (!save_options(s))
  525.         XtPopdown(save_shell);
  526. }
  527.  
  528. /* Called from the "Save Options in File" button on the "File..." menu */
  529. static void
  530. do_save_options(Widget w unused, XtPointer client_data unused,
  531.     XtPointer call_data unused)
  532. {
  533.     if (save_shell == NULL)
  534.         save_shell = create_form_popup("SaveOptions",
  535.             save_button_callback, (XtCallbackProc)NULL, FORM_NO_WHITE);
  536.     XtVaSetValues(XtNameToWidget(save_shell, ObjDialog),
  537.         XtNvalue, profile_name,
  538.         NULL);
  539.     popup_popup(save_shell, XtGrabExclusive);
  540. }
  541.  
  542. #if defined(X3270_PRINTER) /*[*/
  543. /* Callback for printer session options. */
  544. static void
  545. do_printer(Widget w unused, XtPointer client_data, XtPointer call_data unused)
  546. {
  547.     if (client_data == NULL)
  548.         printer_start(CN);
  549.     else if (!strcmp(client_data, "lu"))
  550.         printer_lu_dialog();
  551.     else
  552.         printer_stop();
  553. }
  554. #endif /*]*/
  555.  
  556. static void
  557. file_menu_init(Boolean regen, Dimension x, Dimension y)
  558. {
  559.     static Widget file_menu = (Widget)NULL;
  560.     Widget w;
  561.  
  562.     if (regen && (file_menu != (Widget)NULL)) {
  563.         XtDestroyWidget(file_menu);
  564.         file_menu = (Widget)NULL;
  565.     }
  566.     if (file_menu != (Widget)NULL)
  567.         return;
  568.  
  569.     file_menu = XtVaCreatePopupShell(
  570.         "fileMenu", complexMenuWidgetClass, menu_parent,
  571.         menubar_buttons ? XtNlabel : NULL, NULL,
  572.         NULL);
  573.     if (!menubar_buttons)
  574.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  575.             file_menu, NULL);
  576.  
  577.     /* About x3270... */
  578.     w = XtVaCreateManagedWidget(
  579.         "aboutOption", cmeBSBObjectClass, file_menu,
  580.         NULL);
  581.     XtAddCallback(w, XtNcallback, show_about, NULL);
  582.  
  583. #if defined(X3270_FT) /*[*/
  584.     /* File Transfer */
  585.     if (!appres.secure) {
  586.         (void) XtCreateManagedWidget(
  587.             "space", cmeLineObjectClass, file_menu,
  588.             NULL, 0);
  589.         ft_button = XtVaCreateManagedWidget(
  590.             "ftOption", cmeBSBObjectClass, file_menu,
  591.             XtNsensitive, IN_3270,
  592.             NULL);
  593.         XtAddCallback(ft_button, XtNcallback, popup_ft, NULL);
  594.     }
  595. #endif /*]*/
  596.  
  597. #if defined(X3270_PRINTER) /*[*/
  598.     /* Printer start/stop */
  599.     w = XtVaCreatePopupShell(
  600.         "printerMenu", complexMenuWidgetClass, menu_parent,
  601.         NULL);
  602.     assoc_button = XtVaCreateManagedWidget(
  603.         "assocButton", cmeBSBObjectClass, w,
  604.         XtNsensitive, IN_3270 && IN_TN3270E,
  605.         NULL);
  606.     XtAddCallback(assoc_button, XtNcallback, do_printer, NULL);
  607.     lu_button = XtVaCreateManagedWidget(
  608.         "luButton", cmeBSBObjectClass, w,
  609.         NULL);
  610.     XtAddCallback(lu_button, XtNcallback, do_printer, "lu");
  611.     printer_off_button = XtVaCreateManagedWidget(
  612.         "printerOffButton", cmeBSBObjectClass, w,
  613.         XtNsensitive, printer_running(),
  614.         NULL);
  615.     XtAddCallback(printer_off_button, XtNcallback, do_printer, "off");
  616.  
  617.     (void) XtCreateManagedWidget(
  618.         "space", cmeLineObjectClass, file_menu,
  619.         NULL, 0);
  620.     printer_button = XtVaCreateManagedWidget(
  621.         "printerOption", cmeBSBObjectClass, file_menu,
  622.         XtNsensitive, IN_3270,
  623.         XtNrightBitmap, arrow,
  624.         XtNmenuName, "printerMenu",
  625.         NULL);
  626. #endif /*]*/
  627.  
  628. #if defined(X3270_TRACE) /*[*/
  629.     /* Trace Data Stream
  630.        Trace X Events
  631.        Save Screen(s) in File */
  632.     (void) XtVaCreateManagedWidget(
  633.         "space", cmeLineObjectClass, file_menu,
  634.         NULL);
  635.     if (appres.debug_tracing) {
  636.         toggle_init(file_menu, DS_TRACE, "dsTraceOption", CN);
  637.         toggle_init(file_menu, EVENT_TRACE, "eventTraceOption", CN);
  638.     }
  639.     if (!appres.secure)
  640.         toggle_init(file_menu, SCREEN_TRACE, "screenTraceOption", CN);
  641. #endif /*]*/
  642.  
  643.     /* Print Screen Text */
  644.     (void) XtVaCreateManagedWidget(
  645.         "space", cmeLineObjectClass, file_menu,
  646.         NULL);
  647.     w = XtVaCreateManagedWidget(
  648.         "printTextOption", cmeBSBObjectClass, file_menu,
  649.         NULL);
  650.     XtAddCallback(w, XtNcallback, print_text_option, NULL);
  651.  
  652.     /* Print Window Bitmap */
  653.     w = XtVaCreateManagedWidget(
  654.         "printWindowOption", cmeBSBObjectClass, file_menu,
  655.         NULL);
  656.     XtAddCallback(w, XtNcallback, print_window_option, NULL);
  657.  
  658.     if (!appres.secure) {
  659.  
  660.         /* Save Options */
  661.         (void) XtVaCreateManagedWidget(
  662.             "space", cmeLineObjectClass, file_menu,
  663.             NULL);
  664.         w = XtVaCreateManagedWidget(
  665.             "saveOption", cmeBSBObjectClass, file_menu,
  666.             NULL);
  667.         XtAddCallback(w, XtNcallback, do_save_options, NULL);
  668.  
  669.         /* Execute an action */
  670.         (void) XtVaCreateManagedWidget(
  671.             "space", cmeLineObjectClass, file_menu,
  672.             NULL);
  673.         w = XtVaCreateManagedWidget(
  674.             "executeActionOption", cmeBSBObjectClass, file_menu,
  675.             NULL);
  676.         XtAddCallback(w, XtNcallback, execute_action_option, NULL);
  677.     }
  678.  
  679.     /* Abort script */
  680.     (void) XtVaCreateManagedWidget(
  681.         "space", cmeLineObjectClass, file_menu,
  682.         NULL);
  683.     script_abort_button = XtVaCreateManagedWidget(
  684.         "abortScriptOption", cmeBSBObjectClass, file_menu,
  685.         XtNsensitive, sms_active(),
  686.         NULL);
  687.     XtAddCallback(script_abort_button, XtNcallback, script_abort_callback,
  688.         0);
  689.  
  690.     /* Disconnect */
  691.     (void) XtVaCreateManagedWidget(
  692.         "space", cmeLineObjectClass, file_menu,
  693.         NULL);
  694.     disconnect_button = XtVaCreateManagedWidget(
  695.         "disconnectOption", cmeBSBObjectClass, file_menu,
  696.         XtNsensitive, PCONNECTED,
  697.         NULL);
  698.     XtAddCallback(disconnect_button, XtNcallback, disconnect, 0);
  699.  
  700.     /* Exit x3270 */
  701.     if (exit_menu != (Widget)NULL)
  702.         XtDestroyWidget(exit_menu);
  703.     exit_menu = XtVaCreatePopupShell(
  704.         "exitMenu", complexMenuWidgetClass, menu_parent,
  705.         NULL);
  706.     w = XtVaCreateManagedWidget(
  707.         "exitReallyOption", cmeBSBObjectClass, exit_menu,
  708.         NULL);
  709.     XtAddCallback(w, XtNcallback, Bye, 0);
  710.     exit_button = XtVaCreateManagedWidget(
  711.         "exitOption", cmeBSBObjectClass, file_menu,
  712.         NULL);
  713.     XtAddCallback(exit_button, XtNcallback, Bye, 0);
  714.     n_bye = 1;
  715.  
  716.     /* File... */
  717.     if (menubar_buttons) {
  718.         w = XtVaCreateManagedWidget(
  719.             "fileMenuButton", menuButtonWidgetClass, menu_parent,
  720.             XtNx, x,
  721.             XtNy, y,
  722.             XtNwidth, KEY_WIDTH,
  723.             XtNheight, KEY_HEIGHT,
  724.             XtNmenuName, "fileMenu",
  725.             NULL);
  726.     }
  727. }
  728.  
  729.  
  730. /*
  731.  * "Connect..." menu
  732.  */
  733.  
  734. static Widget connect_shell = NULL;
  735.  
  736. /* Called from each button on the "Connect..." menu */
  737. static void
  738. host_connect_callback(Widget w unused, XtPointer client_data,
  739.     XtPointer call_data unused)
  740. {
  741.     (void) host_connect(client_data);
  742. }
  743.  
  744. /* Called from the lone "Connect" button on the connect dialog */
  745. static void
  746. connect_button_callback(Widget w unused, XtPointer client_data,
  747.     XtPointer call_data unused)
  748. {
  749.     char *s;
  750.  
  751.     s = XawDialogGetValueString((Widget)client_data);
  752.     if (!s || !*s)
  753.         return;
  754.     if (!host_connect(s))
  755.         XtPopdown(connect_shell);
  756. }
  757.  
  758. /* Called from the "Other..." button on the "Connect..." menu */
  759. static void
  760. do_connect_popup(Widget w unused, XtPointer client_data unused,
  761.     XtPointer call_data unused)
  762. {
  763.     if (connect_shell == NULL)
  764.         connect_shell = create_form_popup("Connect",
  765.             connect_button_callback, (XtCallbackProc)NULL, FORM_NO_CC);
  766.     popup_popup(connect_shell, XtGrabExclusive);
  767. }
  768.  
  769. /*
  770.  * Initialize the "Connect..." menu
  771.  */
  772. static void
  773. connect_menu_init(Boolean regen, Position x, Position y)
  774. {
  775.     Widget w;
  776.     int n_hosts = 0;
  777.     Boolean any_hosts = False;
  778.     struct host *h;
  779.     Boolean need_line = False;
  780.     int n_primary = 0;
  781.     int n_recent = 0;
  782.  
  783.     if (regen && (connect_menu != (Widget)NULL)) {
  784.         XtDestroyWidget(connect_menu);
  785.         connect_menu = (Widget)NULL;
  786.         if (connect_button != (Widget)NULL) {
  787.             XtDestroyWidget(connect_button);
  788.             connect_button = (Widget)NULL;
  789.         }
  790.     }
  791.     if (connect_menu != (Widget)NULL)
  792.         return;
  793.  
  794.     /* Create the menu */
  795.     connect_menu = XtVaCreatePopupShell(
  796.         "hostMenu", complexMenuWidgetClass, menu_parent,
  797.         menubar_buttons ? XtNlabel : NULL, NULL,
  798.         NULL);
  799.     if (!menubar_buttons)
  800.         need_line = True;
  801.  
  802.     /* Walk the host list from the file to produce the host menu */
  803.  
  804.     for (h = hosts; h; h = h->next) {
  805.         switch (h->entry_type) {
  806.         case ALIAS:
  807.             continue;
  808.         case PRIMARY:
  809.             /*
  810.              * If there's already a 'recent' entry with the same
  811.              * name, skip this one.
  812.              */
  813.             {
  814.                 struct host *j;
  815.  
  816.                 for (j = hosts;
  817.                      j != (struct host *)NULL;
  818.                      j = j->next) {
  819.                     if (j->entry_type != RECENT) {
  820.                         j = (struct host *)NULL;
  821.                         break;
  822.                     }
  823.                     if (!strcmp(j->name, h->name))
  824.                         break;
  825.                 }
  826.                 if (j != (struct host *)NULL)
  827.                     continue;
  828.             }
  829.             n_primary++;
  830.             break;
  831.         case RECENT:
  832.             n_recent++;
  833.             break;
  834.         }
  835.         if ((need_line && !any_hosts) ||
  836.             (n_recent > 0 && n_primary == 1)) {
  837.             (void) XtVaCreateManagedWidget("space",
  838.                 cmeLineObjectClass, connect_menu, NULL);
  839.         }
  840.         any_hosts = True;
  841.         w = XtVaCreateManagedWidget(
  842.             h->name, cmeBSBObjectClass, connect_menu, 
  843.             NULL);
  844.         XtAddCallback(w, XtNcallback, host_connect_callback,
  845.             XtNewString(h->name));
  846.         n_hosts++;
  847.     }
  848.     if (any_hosts)
  849.         need_line = True;
  850.  
  851.     /* Add an "Other..." button at the bottom */
  852.  
  853.     if (!any_hosts || !appres.no_other) {
  854.         if (need_line)
  855.             (void) XtVaCreateManagedWidget("space",
  856.                 cmeLineObjectClass,
  857.                 connect_menu, NULL);
  858.         w = XtVaCreateManagedWidget(
  859.             "otherHostOption", cmeBSBObjectClass, connect_menu,
  860.             NULL);
  861.         XtAddCallback(w, XtNcallback, do_connect_popup, NULL);
  862.     }
  863.  
  864.     /* Add the "Connect..." button itself to the menu_parent. */
  865.  
  866.     if (menubar_buttons) {
  867.         if (n_hosts) {
  868.             /* Connect button pops up a menu. */
  869.             connect_button = XtVaCreateManagedWidget(
  870.                 "connectMenuButton", menuButtonWidgetClass,
  871.                 menu_parent,
  872.                 XtNx, x,
  873.                 XtNy, y,
  874.                 XtNwidth, KEY_WIDTH,
  875.                 XtNheight, KEY_HEIGHT,
  876.                 XtNmenuName, "hostMenu",
  877.                 XtNmappedWhenManaged, !PCONNECTED,
  878.                 NULL);
  879.         } else {
  880.             /* Connect button pops up a dialog. */
  881.             connect_button = XtVaCreateManagedWidget(
  882.                 "connectMenuButton", commandWidgetClass,
  883.                 menu_parent,
  884.                 XtNx, x,
  885.                 XtNy, y,
  886.                 XtNwidth, KEY_WIDTH,
  887.                 XtNheight, KEY_HEIGHT,
  888.                 XtNmappedWhenManaged, !PCONNECTED,
  889.                 NULL);
  890.             XtAddCallback(connect_button, XtNcallback,
  891.                 do_connect_popup, NULL);
  892.         }
  893.     }
  894. }
  895.  
  896. /*
  897.  * Callback for macros
  898.  */
  899. static void
  900. do_macro(Widget w unused, XtPointer client_data, XtPointer call_data unused)
  901. {
  902.     macro_command((struct macro_def *)client_data);
  903. }
  904.  
  905. /*
  906.  * Initialize the "Macros..." menu
  907.  */
  908. static void
  909. macros_menu_init(Boolean regen, Position x, Position y)
  910. {
  911.     static Widget macros_menu;
  912.     Widget w;
  913.     struct macro_def *m;
  914.     Boolean any = False;
  915.  
  916.     if (regen && (macros_menu != (Widget)NULL)) {
  917.         XtDestroyWidget(macros_menu);
  918.         macros_menu = (Widget)NULL;
  919.         if (macros_button != (Widget)NULL) {
  920.             XtDestroyWidget(macros_button);
  921.             macros_button = (Widget)NULL;
  922.         }
  923.     }
  924.     if (macros_menu != (Widget)NULL || !PCONNECTED)
  925.         return;
  926.  
  927.     /* Walk the list */
  928.  
  929.     macros_init();    /* possibly different for each host */
  930.     for (m = macro_defs; m; m = m->next) {
  931.         if (!any) {
  932.             /* Create the menu */
  933.             macros_menu = XtVaCreatePopupShell(
  934.                 MACROS_MENU, complexMenuWidgetClass, menu_parent,
  935.                 menubar_buttons ? XtNlabel : NULL, NULL,
  936.                 NULL);
  937.             if (!menubar_buttons)
  938.                 (void) XtVaCreateManagedWidget("space",
  939.                     cmeLineObjectClass, macros_menu, NULL);
  940.         }
  941.         w = XtVaCreateManagedWidget(
  942.             m->name, cmeBSBObjectClass, macros_menu, 
  943.             NULL);
  944.         XtAddCallback(w, XtNcallback, do_macro, (XtPointer)m);
  945.         any = True;
  946.     }
  947.  
  948.     /* Add the "Macros..." button itself to the menu_parent */
  949.  
  950.     if (any && menubar_buttons)
  951.         macros_button = XtVaCreateManagedWidget(
  952.             "macrosMenuButton", menuButtonWidgetClass,
  953.             menu_parent,
  954.             XtNx, x,
  955.             XtNy, y,
  956.             XtNwidth, KEY_WIDTH,
  957.             XtNheight, KEY_HEIGHT,
  958.             XtNmenuName, MACROS_MENU,
  959.             NULL);
  960. }
  961.  
  962. /* Called toggle the keypad */
  963. static void
  964. toggle_keypad(Widget w unused, XtPointer client_data unused,
  965.     XtPointer call_data unused)
  966. {
  967.     switch (kp_placement) {
  968.         case kp_integral:
  969.         screen_showikeypad(appres.keypad_on = !appres.keypad_on);
  970.         break;
  971.         case kp_left:
  972.         case kp_right:
  973.         case kp_bottom:
  974.         keypad_popup_init();
  975.         if (keypad_popped) 
  976.             XtPopdown(keypad_shell);
  977.         else
  978.             popup_popup(keypad_shell, XtGrabNone);
  979.         break;
  980.     }
  981.     menubar_keypad_changed();
  982.     keypad_changed = True;
  983. }
  984.  
  985. static void
  986. keypad_button_init(Position x, Position y)
  987. {
  988.     if (!menubar_buttons)
  989.         return;
  990.     if (keypad_button == (Widget)NULL) {
  991.         Pixmap pixmap;
  992.  
  993.         pixmap = XCreateBitmapFromData(display, root_window,
  994.             (char *) ky_bits, ky_width, ky_height);
  995.         keypad_button = XtVaCreateManagedWidget(
  996.             "keypadButton", commandWidgetClass, menu_parent,
  997.             XtNbitmap, pixmap,
  998.             XtNx, x,
  999.             XtNy, y,
  1000.             XtNwidth, ky_width+8,
  1001.             XtNheight, KEY_HEIGHT,
  1002.             NULL);
  1003.         XtAddCallback(keypad_button, XtNcallback,
  1004.             toggle_keypad, NULL);
  1005.     } else {
  1006.         XtVaSetValues(keypad_button, XtNx, x, NULL);
  1007.     }
  1008. }
  1009.  
  1010. void
  1011. menubar_resize(Dimension width)
  1012. {
  1013.     keypad_button_init(
  1014.         (Position) (width - LEFT_MARGIN - (ky_width+8) - 2*BORDER),
  1015.         TOP_MARGIN);
  1016. }
  1017.  
  1018.  
  1019. /*
  1020.  * "Options..." menu
  1021.  */
  1022.  
  1023. static void
  1024. toggle_callback(Widget w, XtPointer userdata, XtPointer calldata unused)
  1025. {
  1026.     struct toggle *t = (struct toggle *) userdata;
  1027.  
  1028.     /*
  1029.      * If this is a two-button radio group, rather than a simple toggle,
  1030.      * there is nothing to do if they are clicking on the current value.
  1031.      *
  1032.      * t->w[0] is the "toggle true" button; t->w[1] is "toggle false".
  1033.      */
  1034.     if (t->w[1] != 0 && w == t->w[!t->value])
  1035.         return;
  1036.  
  1037.     do_toggle(t - appres.toggle);
  1038. }
  1039.  
  1040. static Widget oversize_shell = NULL;
  1041.  
  1042. /* Called from the "Change" button on the oversize dialog */
  1043. static void
  1044. oversize_button_callback(Widget w unused, XtPointer client_data,
  1045.     XtPointer call_data unused)
  1046. {
  1047.     char *s;
  1048.     int ovc, ovr;
  1049.     char junk;
  1050.  
  1051.     s = XawDialogGetValueString((Widget)client_data);
  1052.     if (!s || !*s)
  1053.         return;
  1054.     if (sscanf(s, "%dx%d%c", &ovc, &ovr, &junk) == 2) {
  1055.         XtPopdown(oversize_shell);
  1056.         screen_change_model(model_num, ovc, ovr);
  1057.     } else
  1058.         popup_an_error("Illegal size: %s", s);
  1059. }
  1060.  
  1061. /* Called from the "Oversize..." button on the "Models..." menu */
  1062. static void
  1063. do_oversize_popup(Widget w unused, XtPointer client_data unused,
  1064.     XtPointer call_data unused)
  1065. {
  1066.     if (oversize_shell == NULL)
  1067.         oversize_shell = create_form_popup("Oversize",
  1068.             oversize_button_callback, (XtCallbackProc)NULL,
  1069.             FORM_NO_WHITE);
  1070.     popup_popup(oversize_shell, XtGrabExclusive);
  1071. }
  1072.  
  1073. /* Init a toggle, menu-wise */
  1074. static void
  1075. toggle_init(Widget menu, int ix, const char *name1, const char *name2)
  1076. {
  1077.     struct toggle *t = &appres.toggle[ix];
  1078.  
  1079.     t->label[0] = name1;
  1080.     t->label[1] = name2;
  1081.     t->w[0] = XtVaCreateManagedWidget(
  1082.         name1, cmeBSBObjectClass, menu,
  1083.         XtNleftBitmap,
  1084.          t->value ? (name2 ? diamond : dot) : (name2 ? no_diamond : None),
  1085.         NULL);
  1086.     XtAddCallback(t->w[0], XtNcallback, toggle_callback, (XtPointer) t);
  1087.     if (name2 != NULL) {
  1088.         t->w[1] = XtVaCreateManagedWidget(
  1089.             name2, cmeBSBObjectClass, menu,
  1090.             XtNleftBitmap, t->value ? no_diamond : diamond,
  1091.             NULL);
  1092.         XtAddCallback(t->w[1], XtNcallback, toggle_callback,
  1093.             (XtPointer) t);
  1094.     } else
  1095.         t->w[1] = NULL;
  1096. }
  1097.  
  1098. static Widget *font_widgets;
  1099. static Widget other_font;
  1100. static Widget font_shell = NULL;
  1101.  
  1102. static void
  1103. do_newfont(Widget w unused, XtPointer userdata, XtPointer calldata unused)
  1104. {
  1105.     screen_newfont((char *)userdata, True);
  1106. }
  1107.  
  1108. /* Called from the "Select Font" button on the font dialog */
  1109. static void
  1110. font_button_callback(Widget w, XtPointer client_data,
  1111.     XtPointer call_data unused)
  1112. {
  1113.     char *s;
  1114.  
  1115.     s = XawDialogGetValueString((Widget)client_data);
  1116.     if (!s || !*s)
  1117.         return;
  1118.     XtPopdown(font_shell);
  1119.     do_newfont(w, s, PN);
  1120. }
  1121.  
  1122. static void
  1123. do_otherfont(Widget w unused, XtPointer userdata unused,
  1124.     XtPointer calldata unused)
  1125. {
  1126.     if (font_shell == NULL)
  1127.         font_shell = create_form_popup("Font", font_button_callback,
  1128.                         (XtCallbackProc)NULL,
  1129.                         FORM_NO_CC);
  1130.     popup_popup(font_shell, XtGrabExclusive);
  1131. }
  1132.  
  1133. /* Initialze the color scheme list. */
  1134. static void
  1135. scheme_init(void)
  1136. {
  1137.     char *cm;
  1138.     char *label;
  1139.     char *scheme;
  1140.     struct scheme *s;
  1141.  
  1142.     cm = get_resource(ResSchemeList);
  1143.     if (cm == CN)
  1144.         return;
  1145.     cm = XtNewString(cm);
  1146.  
  1147.     scheme_count = 0;
  1148.     while (split_dresource(&cm, &label, &scheme) == 1) {
  1149.         s = (struct scheme *)XtMalloc(sizeof(struct scheme));
  1150.         s->label = label;
  1151.         s->scheme = scheme;
  1152.         s->next = (struct scheme *)NULL;
  1153.         if (last_scheme != (struct scheme *)NULL)
  1154.             last_scheme->next = s;
  1155.         else
  1156.             schemes = s;
  1157.         last_scheme = s;
  1158.         scheme_count++;
  1159.     }
  1160. }
  1161.  
  1162. static void
  1163. do_newscheme(Widget w unused, XtPointer userdata, XtPointer calldata unused)
  1164. {
  1165.     screen_newscheme((char *)userdata);
  1166. }
  1167.  
  1168. /* Initialze the character set list. */
  1169. static void
  1170. charsets_init(void)
  1171. {
  1172.     char *cm;
  1173.     char *label;
  1174.     char *charset;
  1175.     struct charset *s;
  1176.  
  1177.     cm = get_resource(ResCharsetList);
  1178.     if (cm == CN)
  1179.         return;
  1180.     cm = XtNewString(cm);
  1181.  
  1182.     charset_count = 0;
  1183.     while (split_dresource(&cm, &label, &charset) == 1) {
  1184.         s = (struct charset *)XtMalloc(sizeof(struct charset));
  1185.         s->label = label;
  1186.         s->charset = charset;
  1187.         s->next = (struct charset *)NULL;
  1188.         if (last_charset != (struct charset *)NULL)
  1189.             last_charset->next = s;
  1190.         else
  1191.             charsets = s;
  1192.         last_charset = s;
  1193.         charset_count++;
  1194.     }
  1195. }
  1196.  
  1197. static void
  1198. do_newcharset(Widget w unused, XtPointer userdata, XtPointer calldata unused)
  1199. {
  1200.     struct charset *s;
  1201.     int i;
  1202.  
  1203.     /* Change the character set. */
  1204.     screen_newcharset((char *)userdata);
  1205.  
  1206.     /* Update the menu. */
  1207.     for (i = 0, s = charsets; i < charset_count; i++, s = s->next)
  1208.         XtVaSetValues(charset_widgets[i],
  1209.             XtNleftBitmap,
  1210.             ((appres.charset == CN) ||
  1211.              strcmp(appres.charset, s->charset)) ?
  1212.                 no_diamond : diamond,
  1213.             NULL);
  1214. }
  1215.  
  1216. static Widget keymap_shell = NULL;
  1217.  
  1218. /* Called from the "Set Keymap" button on the keymap dialog */
  1219. static void
  1220. keymap_button_callback(Widget w unused, XtPointer client_data,
  1221.     XtPointer call_data unused)
  1222. {
  1223.     char *s;
  1224.  
  1225.     s = XawDialogGetValueString((Widget)client_data);
  1226.     if (s != CN && !*s)
  1227.         s = CN;
  1228.     XtPopdown(keymap_shell);
  1229.     keymap_init(s);
  1230. }
  1231.  
  1232. /* Callback from the "Keymap" menu option */
  1233. static void
  1234. do_keymap(Widget w unused, XtPointer userdata unused, XtPointer calldata unused)
  1235. {
  1236.     if (keymap_shell == NULL)
  1237.         keymap_shell = create_form_popup("Keymap",
  1238.             keymap_button_callback, (XtCallbackProc)NULL,
  1239.             FORM_NO_WHITE);
  1240.     popup_popup(keymap_shell, XtGrabExclusive);
  1241. }
  1242.  
  1243. /* Called to change telnet modes */
  1244. static void
  1245. linemode_callback(Widget w unused, XtPointer client_data unused, XtPointer call_data unused)
  1246. {
  1247.     net_linemode();
  1248. }
  1249.  
  1250. static void
  1251. charmode_callback(Widget w unused, XtPointer client_data unused, 
  1252.     XtPointer call_data unused)
  1253. {
  1254.     net_charmode();
  1255. }
  1256.  
  1257. /* Called to change models */
  1258. static void
  1259. change_model_callback(Widget w, XtPointer client_data,
  1260.     XtPointer call_data unused)
  1261. {
  1262.     int m;
  1263.  
  1264.     m = atoi(client_data);
  1265.     switch (model_num) {
  1266.         case 2:
  1267.         XtVaSetValues(model_2_button, XtNleftBitmap, no_diamond, NULL);
  1268.         break;
  1269.         case 3:
  1270.         XtVaSetValues(model_3_button, XtNleftBitmap, no_diamond, NULL);
  1271.         break;
  1272.         case 4:
  1273.         XtVaSetValues(model_4_button, XtNleftBitmap, no_diamond, NULL);
  1274.         break;
  1275.         case 5:
  1276.         XtVaSetValues(model_5_button, XtNleftBitmap, no_diamond, NULL);
  1277.         break;
  1278.     }
  1279.     XtVaSetValues(w, XtNleftBitmap, diamond, NULL);
  1280.     screen_change_model(m, 0, 0);
  1281. }
  1282.  
  1283. /* Called to when model changes outside our control */
  1284. static void
  1285. menubar_remodel(Boolean ignored unused)
  1286. {
  1287.     XtVaSetValues(model_2_button, XtNleftBitmap,
  1288.         (model_num == 2)? diamond: no_diamond, NULL);
  1289.     XtVaSetValues(model_3_button, XtNleftBitmap,
  1290.         (model_num == 3)? diamond: no_diamond, NULL);
  1291.     XtVaSetValues(model_4_button, XtNleftBitmap,
  1292.         (model_num == 4)? diamond: no_diamond, NULL);
  1293.     XtVaSetValues(model_5_button, XtNleftBitmap,
  1294.         (model_num == 5)? diamond: no_diamond, NULL);
  1295. }
  1296.  
  1297. /* Called to change emulation modes */
  1298. static void
  1299. toggle_extended(Widget w unused, XtPointer client_data unused,
  1300.     XtPointer call_data unused)
  1301. {
  1302.     appres.extended = !appres.extended;
  1303.     XtVaSetValues(extended_button, XtNleftBitmap,
  1304.         appres.extended ? dot : (Pixmap)NULL,
  1305.         NULL);
  1306.     XtVaSetValues(oversize_button, XtNsensitive, appres.extended, NULL);
  1307.     if (!appres.extended)
  1308.         screen_change_model(model_num, 0, 0);
  1309.     screen_extended(appres.extended);
  1310. }
  1311.  
  1312. static void
  1313. toggle_m3279(Widget w, XtPointer client_data unused, XtPointer call_data unused)
  1314. {
  1315.     if (w == m3278_button)
  1316.         appres.m3279 = False;
  1317.     else if (w == m3279_button)
  1318.         appres.m3279 = True;
  1319.     else
  1320.         return;
  1321.     XtVaSetValues(m3278_button, XtNleftBitmap,
  1322.         appres.m3279 ? no_diamond : diamond,
  1323.         NULL);
  1324.     XtVaSetValues(m3279_button, XtNleftBitmap,
  1325.         appres.m3279 ? diamond : no_diamond,
  1326.         NULL);
  1327. #if defined(RESTRICT_3279) /*[*/
  1328.     XtVaSetValues(model_4_button, XtNsensitive, !appres.m3279, NULL);
  1329.     XtVaSetValues(model_5_button, XtNsensitive, !appres.m3279, NULL);
  1330.     if (model_num == 4 || model_num == 5)
  1331.         screen_change_model(3, 0, 0);
  1332. #endif /*]*/
  1333.     if (scheme_button != (Widget)NULL)
  1334.         XtVaSetValues(scheme_button, XtNsensitive, appres.m3279, NULL);
  1335.     screen_m3279(appres.m3279);
  1336. }
  1337.  
  1338. static void
  1339. options_menu_init(Boolean regen, Position x, Position y)
  1340. {
  1341.     static Widget options_menu;
  1342.     Widget t, w;
  1343.     struct font_list *f;
  1344.     struct scheme *s;
  1345.     int ix;
  1346.  
  1347.     if (regen && (options_menu != (Widget)NULL)) {
  1348.         XtDestroyWidget(options_menu);
  1349.         options_menu = (Widget)NULL;
  1350.     }
  1351.     if (options_menu != (Widget)NULL) {
  1352.         /* Set the current font. */
  1353.         for (f = font_list, ix = 0; f; f = f->next, ix++) {
  1354.             XtVaSetValues(font_widgets[ix], XtNleftBitmap,
  1355.                 !strcmp(efontname, f->font) ?
  1356.                     diamond : no_diamond,
  1357.                 NULL);
  1358.         }
  1359.         /* Set the current color scheme. */
  1360.         s = schemes;
  1361.         for (ix = 0, s = schemes;
  1362.              ix < scheme_count;
  1363.              ix++, s = s->next) {
  1364.             XtVaSetValues(scheme_widgets[ix], XtNleftBitmap,
  1365.                 !strcmp(appres.color_scheme, s->scheme) ?
  1366.                     diamond : no_diamond,
  1367.                 NULL);
  1368.         }
  1369.         return;
  1370.     }
  1371.  
  1372.     /* Create the shell */
  1373.     options_menu = XtVaCreatePopupShell(
  1374.         "optionsMenu", complexMenuWidgetClass, menu_parent,
  1375.         menubar_buttons ? XtNlabel : NULL, NULL,
  1376.         NULL);
  1377.     if (!menubar_buttons)
  1378.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  1379.             options_menu, NULL);
  1380.  
  1381.     /* Create the "toggles" pullright */
  1382.     t = XtVaCreatePopupShell(
  1383.         "togglesMenu", complexMenuWidgetClass, menu_parent,
  1384.         NULL);
  1385.     if (!menubar_buttons) {
  1386.         keypad_option_button = XtVaCreateManagedWidget(
  1387.             "keypadOption", cmeBSBObjectClass, t,
  1388.             XtNleftBitmap,
  1389.             appres.keypad_on || keypad_popped ? dot : None,
  1390.             NULL);
  1391.         XtAddCallback(keypad_option_button, XtNcallback, toggle_keypad,
  1392.             PN);
  1393.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  1394.             t, NULL);
  1395.     }
  1396.     toggle_init(t, MONOCASE, "monocaseOption", CN);
  1397.     toggle_init(t, CURSOR_BLINK, "cursorBlinkOption", CN);
  1398.     toggle_init(t, BLANK_FILL, "blankFillOption", CN);
  1399.     toggle_init(t, SHOW_TIMING, "showTimingOption", CN);
  1400.     toggle_init(t, CURSOR_POS, "cursorPosOption", CN);
  1401.     toggle_init(t, SCROLL_BAR, "scrollBarOption", CN);
  1402. #if defined(X3270_ANSI) /*[*/
  1403.     toggle_init(t, LINE_WRAP, "lineWrapOption", CN);
  1404. #endif /*]*/
  1405.     toggle_init(t, MARGINED_PASTE, "marginedPasteOption", CN);
  1406.     toggle_init(t, RECTANGLE_SELECT, "rectangleSelectOption", CN);
  1407.     (void) XtVaCreateManagedWidget("space", cmeLineObjectClass, t, NULL);
  1408.     toggle_init(t, ALT_CURSOR, "underlineCursorOption",
  1409.         "blockCursorOption");
  1410.     (void) XtVaCreateManagedWidget("space", cmeLineObjectClass, t, NULL);
  1411.     linemode_button = XtVaCreateManagedWidget(
  1412.         "lineModeOption", cmeBSBObjectClass, t,
  1413.         XtNleftBitmap, linemode ? diamond : no_diamond,
  1414.         XtNsensitive, IN_ANSI,
  1415.         NULL);
  1416.     XtAddCallback(linemode_button, XtNcallback, linemode_callback, NULL);
  1417.     charmode_button = XtVaCreateManagedWidget(
  1418.         "characterModeOption", cmeBSBObjectClass, t,
  1419.         XtNleftBitmap, linemode ? no_diamond : diamond,
  1420.         XtNsensitive, IN_ANSI,
  1421.         NULL);
  1422.     XtAddCallback(charmode_button, XtNcallback, charmode_callback, NULL);
  1423.     if (!appres.mono) {
  1424.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass, t,
  1425.             NULL);
  1426.         m3278_button = XtVaCreateManagedWidget(
  1427.             "m3278Option", cmeBSBObjectClass, t,
  1428.             XtNleftBitmap, appres.m3279 ? no_diamond : diamond,
  1429.             XtNsensitive, !PCONNECTED,
  1430.             NULL);
  1431.         XtAddCallback(m3278_button, XtNcallback, toggle_m3279, NULL);
  1432.         m3279_button = XtVaCreateManagedWidget(
  1433.             "m3279Option", cmeBSBObjectClass, t,
  1434.             XtNleftBitmap, appres.m3279 ? diamond : no_diamond,
  1435.             XtNsensitive, !PCONNECTED,
  1436.             NULL);
  1437.         XtAddCallback(m3279_button, XtNcallback, toggle_m3279, NULL);
  1438.     }
  1439.     (void) XtVaCreateManagedWidget("space", cmeLineObjectClass, t,
  1440.         NULL);
  1441.     extended_button = XtVaCreateManagedWidget(
  1442.         "extendedDsOption", cmeBSBObjectClass, t,
  1443.         XtNleftBitmap, appres.extended ? dot : (Pixmap)NULL,
  1444.         XtNsensitive, !PCONNECTED,
  1445.         NULL);
  1446.     XtAddCallback(extended_button, XtNcallback, toggle_extended, NULL);
  1447.     (void) XtVaCreateManagedWidget(
  1448.         "togglesOption", cmeBSBObjectClass, options_menu,
  1449.         XtNrightBitmap, arrow,
  1450.         XtNmenuName, "togglesMenu",
  1451.         NULL);
  1452.  
  1453.     (void) XtVaCreateManagedWidget(
  1454.         "space", cmeLineObjectClass, options_menu,
  1455.         NULL);
  1456.  
  1457.     /* Create the "fonts" pullright */
  1458.     t = XtVaCreatePopupShell(
  1459.         "fontsMenu", complexMenuWidgetClass, menu_parent,
  1460.         NULL);
  1461.     font_widgets = (Widget *)XtCalloc(font_count, sizeof(Widget));
  1462.     for (f = font_list, ix = 0; f; f = f->next, ix++) {
  1463.         font_widgets[ix] = XtVaCreateManagedWidget(
  1464.             f->label, cmeBSBObjectClass, t,
  1465.             XtNleftBitmap,
  1466.             !strcmp(efontname, f->font) ? diamond : no_diamond,
  1467.             NULL);
  1468.         XtAddCallback(font_widgets[ix], XtNcallback, do_newfont,
  1469.             f->font);
  1470.     }
  1471.     if (!appres.no_other) {
  1472.         other_font = XtVaCreateManagedWidget(
  1473.             "otherFontOption", cmeBSBObjectClass, t,
  1474.             NULL);
  1475.         XtAddCallback(other_font, XtNcallback, do_otherfont, NULL);
  1476.     }
  1477.     (void) XtVaCreateManagedWidget(
  1478.         "fontsOption", cmeBSBObjectClass, options_menu,
  1479.         XtNrightBitmap, arrow,
  1480.         XtNmenuName, "fontsMenu",
  1481.         XtNsensitive, appres.apl_mode ? False : True,
  1482.         NULL);
  1483.  
  1484.     (void) XtVaCreateManagedWidget(
  1485.         "space", cmeLineObjectClass, options_menu,
  1486.         NULL);
  1487.  
  1488.     /* Create the "models" pullright */
  1489.     t = XtVaCreatePopupShell(
  1490.         "modelsMenu", complexMenuWidgetClass, menu_parent,
  1491.         NULL);
  1492.     model_2_button = XtVaCreateManagedWidget(
  1493.         "model2Option", cmeBSBObjectClass, t,
  1494.         XtNleftBitmap, model_num == 2 ? diamond : no_diamond,
  1495.         NULL);
  1496.     XtAddCallback(model_2_button, XtNcallback, change_model_callback,
  1497.         XtNewString("2"));
  1498.     model_3_button = XtVaCreateManagedWidget(
  1499.         "model3Option", cmeBSBObjectClass, t,
  1500.         XtNleftBitmap, model_num == 3 ? diamond : no_diamond,
  1501.         NULL);
  1502.     XtAddCallback(model_3_button, XtNcallback, change_model_callback,
  1503.         XtNewString("3"));
  1504.     model_4_button = XtVaCreateManagedWidget(
  1505.         "model4Option", cmeBSBObjectClass, t,
  1506.         XtNleftBitmap, model_num == 4 ? diamond : no_diamond,
  1507. #if defined(RESTRICT_3279) /*[*/
  1508.         XtNsensitive, !appres.m3279,
  1509. #endif /*]*/
  1510.         NULL);
  1511.     XtAddCallback(model_4_button, XtNcallback,
  1512.         change_model_callback, XtNewString("4"));
  1513.     model_5_button = XtVaCreateManagedWidget(
  1514.         "model5Option", cmeBSBObjectClass, t,
  1515.         XtNleftBitmap, model_num == 5 ? diamond : no_diamond,
  1516. #if defined(RESTRICT_3279) /*[*/
  1517.         XtNsensitive, !appres.m3279,
  1518. #endif /*]*/
  1519.         NULL);
  1520.     XtAddCallback(model_5_button, XtNcallback,
  1521.         change_model_callback, XtNewString("5"));
  1522.     oversize_button = XtVaCreateManagedWidget(
  1523.         "oversizeOption", cmeBSBObjectClass, t,
  1524.         XtNsensitive, appres.extended,
  1525.         NULL);
  1526.     XtAddCallback(oversize_button, XtNcallback, do_oversize_popup, NULL);
  1527.     models_option = XtVaCreateManagedWidget(
  1528.         "modelsOption", cmeBSBObjectClass, options_menu,
  1529.         XtNrightBitmap, arrow,
  1530.         XtNmenuName, "modelsMenu",
  1531.         XtNsensitive, !PCONNECTED,
  1532.         NULL);
  1533.  
  1534.     /* Create the "colors" pullright */
  1535.     if (scheme_count) {
  1536.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  1537.             options_menu,
  1538.             NULL);
  1539.  
  1540.         scheme_widgets = (Widget *)XtCalloc(scheme_count,
  1541.             sizeof(Widget));
  1542.         t = XtVaCreatePopupShell(
  1543.             "colorsMenu", complexMenuWidgetClass, menu_parent,
  1544.             NULL);
  1545.         s = schemes;
  1546.         for (ix = 0, s = schemes; ix < scheme_count; ix++, s = s->next) {
  1547.             scheme_widgets[ix] = XtVaCreateManagedWidget(
  1548.                 s->label, cmeBSBObjectClass, t,
  1549.                 XtNleftBitmap,
  1550.                 !strcmp(appres.color_scheme, s->scheme) ?
  1551.                     diamond : no_diamond,
  1552.                 NULL);
  1553.             XtAddCallback(scheme_widgets[ix], XtNcallback,
  1554.                 do_newscheme, s->scheme);
  1555.         }
  1556.         scheme_button = XtVaCreateManagedWidget(
  1557.             "colorsOption", cmeBSBObjectClass, options_menu,
  1558.             XtNrightBitmap, arrow,
  1559.             XtNmenuName, "colorsMenu",
  1560.             XtNsensitive, appres.m3279,
  1561.             NULL);
  1562.     }
  1563.  
  1564.     /* Create the "character set" pullright */
  1565.     if (charset_count) {
  1566.         struct charset *cs;
  1567.  
  1568.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  1569.             options_menu,
  1570.             NULL);
  1571.  
  1572.         charset_widgets = (Widget *)XtCalloc(charset_count,
  1573.             sizeof(Widget));
  1574.         t = XtVaCreatePopupShell(
  1575.             "charsetMenu", complexMenuWidgetClass, menu_parent,
  1576.             NULL);
  1577.         for (ix = 0, cs = charsets;
  1578.                      ix < charset_count;
  1579.                      ix++, cs = cs->next) {
  1580.             charset_widgets[ix] = XtVaCreateManagedWidget(
  1581.                 cs->label, cmeBSBObjectClass, t,
  1582.                 XtNleftBitmap,
  1583.                 ((appres.charset == CN) ||
  1584.                  strcmp(appres.charset, cs->charset)) ?
  1585.                     no_diamond : diamond,
  1586.                 NULL);
  1587.             XtAddCallback(charset_widgets[ix], XtNcallback,
  1588.                 do_newcharset, cs->charset);
  1589.         }
  1590.         (void) XtVaCreateManagedWidget(
  1591.             "charsetOption", cmeBSBObjectClass, options_menu,
  1592.             XtNrightBitmap, arrow,
  1593.             XtNmenuName, "charsetMenu",
  1594.             NULL);
  1595.     }
  1596.  
  1597.     /* Create the "keymap" option */
  1598.     if (!appres.no_other) {
  1599.         (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  1600.             options_menu,
  1601.             NULL);
  1602.         w = XtVaCreateManagedWidget(
  1603.             "keymapOption", cmeBSBObjectClass, options_menu,
  1604.             NULL);
  1605.         XtAddCallback(w, XtNcallback, do_keymap, NULL);
  1606.     }
  1607.  
  1608.     /* Create the "display keymap" option */
  1609.     (void) XtVaCreateManagedWidget("space", cmeLineObjectClass,
  1610.         options_menu,
  1611.         NULL);
  1612.     w = XtVaCreateManagedWidget(
  1613.         "keymapDisplayOption", cmeBSBObjectClass, options_menu,
  1614.         NULL);
  1615.     XtAddCallback(w, XtNcallback, do_keymap_display, NULL);
  1616.  
  1617.     if (menubar_buttons) {
  1618.         (void) XtVaCreateManagedWidget(
  1619.             "optionsMenuButton", menuButtonWidgetClass, menu_parent,
  1620.             XtNx, x,
  1621.             XtNy, y,
  1622.             XtNwidth, KEY_WIDTH,
  1623.             XtNheight, KEY_HEIGHT,
  1624.             XtNmenuName, "optionsMenu",
  1625.             NULL);
  1626.         keypad_option_button = NULL;
  1627.     }
  1628. }
  1629.  
  1630. /*
  1631.  * Change a menu checkmark
  1632.  */
  1633. void
  1634. menubar_retoggle(struct toggle *t)
  1635. {
  1636.     XtVaSetValues(t->w[0],
  1637.         XtNleftBitmap, t->value ? (t->w[1] ? diamond : dot) : None,
  1638.         NULL);
  1639.     if (t->w[1] != NULL)
  1640.         XtVaSetValues(t->w[1],
  1641.             XtNleftBitmap, t->value ? no_diamond : diamond,
  1642.             NULL);
  1643. }
  1644.  
  1645. void
  1646. HandleMenu_action(Widget w unused, XEvent *event, String *params,
  1647.     Cardinal *num_params)
  1648. {
  1649.     String p;
  1650.  
  1651.     action_debug(HandleMenu_action, event, params, num_params);
  1652.     if (check_usage(HandleMenu_action, *num_params, 1, 2) < 0)
  1653.         return;
  1654.     if (!CONNECTED || *num_params == 1)
  1655.         p = params[0];
  1656.     else
  1657.         p = params[1];
  1658.     if (!XtNameToWidget(menu_parent, p)) {
  1659.         if (strcmp(p, MACROS_MENU))
  1660.             popup_an_error("%s: cannot find menu %s",
  1661.                 action_name(HandleMenu_action), p);
  1662.         return;
  1663.     }
  1664.     XtCallActionProc(menu_parent, "XawPositionComplexMenu", event, &p, 1);
  1665.     XtCallActionProc(menu_parent, "MenuPopup", event, &p, 1);
  1666. }
  1667.  
  1668. #endif /*]*/
  1669.